package handling.channel;

import client.MapleCharacter;
import client.MapleCharacterUtil;
import client.MapleClient;
import handling.world.CharacterTransfer;
import handling.world.CheaterData;
import handling.world.World.Find;
import server.Timer.PingTimer;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class PlayerStorage {
    private ReentrantReadWriteLock mutex;
    private Lock readLock;
    private Lock writeLock;
    private ReentrantReadWriteLock mutex2;
    private Lock readLock2;
    private Lock writeLock2;
    private ReentrantReadWriteLock mutex3;
    private Lock readLock3;
    private Lock writeLock3;
    private Map<Integer, MapleCharacter> idToChar;
    private Map<Integer, CharacterTransfer> PendingCharacter;
    private Map<Integer, MapleClient> PendingClient;
    private int channel;

    public PlayerStorage(int channel) {
        this.mutex = new ReentrantReadWriteLock();
        this.readLock = this.mutex.readLock();
        this.writeLock = this.mutex.writeLock();
        this.mutex2 = new ReentrantReadWriteLock();
        this.readLock2 = this.mutex2.readLock();
        this.writeLock2 = this.mutex2.writeLock();
        this.mutex3 = new ReentrantReadWriteLock();
        this.readLock3 = this.mutex3.readLock();
        this.writeLock3 = this.mutex3.writeLock();
        this.idToChar = (Map<Integer, MapleCharacter>) new HashMap();
        this.PendingCharacter = (Map<Integer, CharacterTransfer>) new HashMap();
        this.PendingClient = (Map<Integer, MapleClient>) new HashMap();
        this.channel = channel;
        PingTimer.getInstance().register((Runnable) new PersistingTask(), 60000L);
    }

    public Collection<MapleClient> getAllPendingClients() {
        this.readLock.lock();
        try {
            return this.PendingClient.values();
        }
        finally {
            this.readLock.unlock();
        }
    }

    public Collection<MapleCharacter> getAllCharacters() {
        this.readLock.lock();
        try {
            return new ArrayList(this.idToChar.values());
        }
        finally {
            this.readLock.unlock();
        }
    }

    public List<MapleCharacter> getAllCharactersThreadSafe() {
        List<MapleCharacter> ret = (List<MapleCharacter>) new ArrayList();
        try {
            ret.addAll(this.getAllCharacters());
        } catch (ConcurrentModificationException ex) {
        }
        return ret;
    }

    public void registerPlayer(MapleCharacter chr) {
        this.writeLock.lock();
        try {
            this.idToChar.put(Integer.valueOf(chr.getId()), chr);
        }
        finally {
            this.writeLock.unlock();
        }
        Find.register(chr.getId(), chr.getName(), this.channel);
    }

    public void registerPendingPlayer(CharacterTransfer chr, int playerid) {
        this.writeLock2.lock();
        try {
            this.PendingCharacter.put(Integer.valueOf(playerid), chr);
        }
        finally {
            this.writeLock2.unlock();
        }
    }

    public void deregisterPlayer(MapleCharacter chr) {
        this.writeLock.lock();
        try {
            this.idToChar.remove(Integer.valueOf(chr.getId()));
        }
        finally {
            this.writeLock.unlock();
        }
        Find.forceDeregister(chr.getId(), chr.getName());
    }

    public int pendingCharacterSize(int world) {
        Map<Integer, MapleCharacter> chars = (Map<Integer, MapleCharacter>) new HashMap();
        for (MapleCharacter chr : this.idToChar.values()) {
            if (chr.getWorld() == world) {
                chars.put(Integer.valueOf(chr.getId()), chr);
            }
        }
        return chars.size();
    }

    public int pendingCharacterSize() {
        return this.PendingCharacter.size();
    }

    public void deregisterPlayer(int idz, String namez) {
        this.writeLock.lock();
        try {
            this.idToChar.remove(Integer.valueOf(idz));
        }
        finally {
            this.writeLock.unlock();
        }
        Find.forceDeregister(idz, namez);
    }

    public void deregisterPendingPlayer(int charid) {
        this.writeLock2.lock();
        try {
            this.PendingCharacter.remove(Integer.valueOf(charid));
        }
        finally {
            this.writeLock2.unlock();
        }
    }

    public CharacterTransfer getPendingCharacter(int charid) {
        this.readLock2.lock();
        CharacterTransfer toreturn;
        try {
            toreturn = (CharacterTransfer) this.PendingCharacter.get(Integer.valueOf(charid));
        }
        finally {
            this.readLock2.unlock();
        }
        if (toreturn != null) {
            this.deregisterPendingPlayer(charid);
        }
        return toreturn;
    }

    public MapleCharacter getCharacterByName(String name) {
        MapleCharacter rchr = null;
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getName().equalsIgnoreCase(name)) {
                    rchr = chr;
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
        return rchr;
    }

    public MapleCharacter getCharacterById(int id) {
        this.readLock.lock();
        try {
            return (MapleCharacter) this.idToChar.get(Integer.valueOf(id));
        }
        finally {
            this.readLock.unlock();
        }
    }

    public int getConnectedClients() {
        return this.idToChar.size();
    }

    public List<CheaterData> getCheaters() {
        List<CheaterData> cheaters = (List<CheaterData>) new ArrayList();
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getCheatTracker().getPoints() > 0) {
                    cheaters.add(new CheaterData(chr.getCheatTracker().getPoints(), MapleCharacterUtil.makeMapleReadable(chr.getName()) + "(编号:" + chr.getId() + ") 检测次数(" + chr.getCheatTracker().getPoints() + ") " + chr.getCheatTracker().getSummary() + " 地图:" + chr.getMap().getMapName()));
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
        return cheaters;
    }

    public void disconnectAll() {
        this.disconnectAll(false);
    }

    public void disconnectAll(boolean checkGM) {
        this.writeLock.lock();
        try {
            Iterator<MapleCharacter> itr = this.idToChar.values().iterator();
            while (itr.hasNext()) {
                MapleCharacter chr = (MapleCharacter) itr.next();
                if (!chr.isGM() || !checkGM) {
                    chr.getClient().disconnect(false, false, true);
                    chr.getClient().getSession().close();
                    Find.forceDeregister(chr.getId(), chr.getName());
                    itr.remove();
                }
            }
        }
        finally {
            this.writeLock.unlock();
        }
    }

    public void disconnectAll(MapleCharacter ch) {
        this.writeLock.lock();
        try {
            Iterator<MapleCharacter> itr = this.idToChar.values().iterator();
            while (itr.hasNext()) {
                MapleCharacter chr = (MapleCharacter) itr.next();
                if (chr.getGMLevel() < ch.getGMLevel()) {
                    chr.getClient().disconnect(false, false, true);
                    chr.getClient().getSession().close();
                    Find.forceDeregister(chr.getId(), chr.getName());
                    itr.remove();
                }
            }
        }
        finally {
            this.writeLock.unlock();
        }
    }

    public String getOnlinePlayers(boolean byGM) {
        StringBuilder sb = new StringBuilder();
        if (byGM) {
            this.readLock.lock();
            try {
                Iterator<MapleCharacter> itr = this.idToChar.values().iterator();
                while (itr.hasNext()) {
                    sb.append(MapleCharacterUtil.makeMapleReadable(((MapleCharacter) itr.next()).getName()));
                    sb.append(", ");
                }
            }
            finally {
                this.readLock.unlock();
            }
        } else {
            this.readLock.lock();
            try {
                for (MapleCharacter chr : this.idToChar.values()) {
                    if (!chr.isGM()) {
                        sb.append(MapleCharacterUtil.makeMapleReadable(chr.getName()));
                        sb.append(", ");
                    }
                }
            }
            finally {
                this.readLock.unlock();
            }
        }
        return sb.toString();
    }

    public void broadcastPacket(byte[] data) {
        this.readLock.lock();
        try {
            Iterator<MapleCharacter> itr = this.idToChar.values().iterator();
            while (itr.hasNext()) {
                ((MapleCharacter) itr.next()).getClient().sendPacket(data);
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public void broadcastSmegaPacket(byte[] data) {
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getClient().isLoggedIn() && chr.getSmega()) {
                    chr.getClient().sendPacket(data);
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public void broadcastGashponmegaPacket(byte[] data) {
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getClient().isLoggedIn() && chr.getGashponmega()) {
                    chr.getClient().sendPacket(data);
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public void broadcastGMPacket(byte[] data) {
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getClient().isLoggedIn() && chr.isGM()) {
                    chr.getClient().sendPacket(data);
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public void broadcastGMPacket(byte[] data, boolean 吸怪) {
        this.readLock.lock();
        try {
            for (MapleCharacter chr : this.idToChar.values()) {
                if (chr.getClient().isLoggedIn() && chr.isGM() && chr.get_control_吸怪讯息()) {
                    chr.getClient().sendPacket(data);
                }
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public MapleClient getPendingClient(int charid) {
        this.readLock3.lock();
        MapleClient toreturn;
        try {
            toreturn = (MapleClient) this.PendingClient.get(Integer.valueOf(charid));
        }
        finally {
            this.readLock3.unlock();
        }
        if (toreturn != null) {
            this.deregisterPendingClient(charid);
        }
        return toreturn;
    }

    public void registerPendingClient(MapleClient c, int playerid) {
        this.writeLock3.lock();
        try {
            this.PendingClient.put(Integer.valueOf(playerid), c);
        }
        finally {
            this.writeLock3.unlock();
        }
    }

    public void deregisterPendingClient(int charid) {
        this.writeLock3.lock();
        try {
            this.PendingClient.remove(Integer.valueOf(charid));
        }
        finally {
            this.writeLock3.unlock();
        }
    }

    public void deregisterPendingPlayerByAccountId(int accountId) {
        this.writeLock2.lock();
        try {
            for (CharacterTransfer transfer : this.PendingCharacter.values()) {
                if (transfer.accountid == accountId) {
                    this.PendingCharacter.remove(Integer.valueOf(transfer.characterid));
                }
            }
        }
        finally {
            this.writeLock2.unlock();
        }
    }

    public void 断所有人(boolean checkGM) {
        this.readLock.lock();
        try {
            Iterator<MapleCharacter> itr = this.idToChar.values().iterator();
            while (itr.hasNext()) {
                MapleCharacter chr = (MapleCharacter) itr.next();
                chr.getClient().disconnect(false, false, true);
                chr.getClient().getSession().close();
                Find.forceDeregister(chr.getId(), chr.getName());
                itr.remove();
            }
        }
        finally {
            this.readLock.unlock();
        }
    }

    public class PersistingTask implements Runnable {
        @Override
        public void run() {
            PlayerStorage.this.writeLock2.lock();
            try {
                long currenttime = System.currentTimeMillis();
                Iterator<Entry<Integer, CharacterTransfer>> itr = PlayerStorage.this.PendingCharacter.entrySet().iterator();
                while (itr.hasNext()) {
                    if (currenttime - ((CharacterTransfer) ((Entry<Integer, CharacterTransfer>) itr.next()).getValue()).TranferTime > 40000L) {
                        itr.remove();
                    }
                }
            }
            finally {
                PlayerStorage.this.writeLock2.unlock();
            }
        }
    }
}
